// $codepro.audit.disable numericLiterals, overloadedMethods
/**
 * uses view package
 */
package javamonsters.view;
import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.FontFormatException;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;

import javamonsters.controller.ConfigViewController;
import javamonsters.controller.Controller;
import javamonsters.controller.MarketplaceController;
import javamonsters.controller.ShipYardController;
import javamonsters.controller.TitleScreenViewController;
import javamonsters.controller.UniverseSideViewController;
import javamonsters.model.Marketplace;
import javamonsters.model.Player;
import javamonsters.model.SolarSystem;
import javamonsters.universe.application.UniverseController;
import javamonsters.universe.model.DefaultUniverseModel;
import javamonsters.universe.model.interfaces.UniverseModel;
import javamonsters.universe.presentation.DefaultUniverseView;
import javamonsters.universe.presentation.interfaces.UniverseView;

import javax.swing.JFrame;
import javax.swing.JOptionPane;


import sun.audio.AudioData;
import sun.audio.AudioPlayer;
import sun.audio.AudioStream;
import sun.audio.ContinuousAudioDataStream;

/**
 * SpaceTraders is the main class for the Space Traders game.
 * 
 * @author elahurd3
 * @version 1.0
 */
public class SpaceTraders extends JFrame implements Controller {
	
	/**
	 * instance variable for TitleScreenView
	 */
	private final TitleScreenView main;
	
	/**
	 * object input stream for player
	 */
	private ObjectInputStream playerIn;
	
    /**
     * object input stream for universe
     */
    private ObjectInputStream universeIn;
	
	/**
	 * instance variable for ConfigView
	 */
	private final ConfigView config;
	
	/**
	 * instance variable for DualUniversePanel
	 */
	private final DualUniversePanel dual;
	
	/**
	 * instance variable for UniverseSideView
	 */
	private final UniverseSideView side;
	
	/**
	 * instance variable for MarketplaceView
	 */
	private final MarketplaceView mktplcView;

	/**
	 * instance variable for ShipYardView
	 */
	private final ShipYardView shipYardView;
	
	/**
	 * instance variable for UniverseController
	 */
	private final UniverseController universeController;

	/**
	 * instance variable for TitleScreenViewController
	 */
	@SuppressWarnings("unused")
	private final TitleScreenViewController titleController;

	/**
	 * instance variable for ConfigViewController
	 */
	@SuppressWarnings("unused")
	private final ConfigViewController configController;
	
	/**
	 * instance variable for MarketplaceController
	 */
	private final MarketplaceController mktplcController;
	
	/**
	 * instance variable for UniverseSideViewController
	 */
	private final UniverseSideViewController universeSideViewController;
	
	/**
	 * instance variable for ShipYardController
	 */
	private final ShipYardController shipYardController;
	
	/**
	 * instance variable for MainPanel
	 */
	private final MainPanel card;
	
	/**
	 * instance variable for Player
	 */
	private Player player;
	
	/**
	 * instance variable for AudioPlayer
	 */
	private AudioPlayer audioPlayer;
	
	/**
	 * instance variable for ContinuousAudioDataStream
	 */
	private ContinuousAudioDataStream loop;
	
	/**
	 * instance variable for AudioStream
	 */
	private AudioStream audioStream;
	
	/**
	 * instance variable for AudioData
	 */
	private AudioData data;
	
	/**
	 * Launch the application.
	 * @param args 
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			@Override
			public void run() {
				try {
					final SpaceTraders frame = new SpaceTraders();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Constructor which instantiates controllers and views
	 * @throws IOException 
	 * @throws FontFormatException 
	 * @throws InterruptedException 
	 */
	public SpaceTraders() throws FontFormatException, IOException {
		super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		super.setBounds(400, 100, 700, 380);
		super.setBackground(Color.BLACK);
		super.setTitle("Space Traders");
		music();
		
		config = new ConfigView();
		main = new TitleScreenView();
		side = new UniverseSideView(this);
		shipYardView = new ShipYardView();
		
		final UniverseView universeView = new DefaultUniverseView();
		final UniverseModel universeModel = new DefaultUniverseModel();
		dual = new DualUniversePanel();
		dual.add((Component) universeView);
		dual.add(side);
		universeController = new UniverseController(
				universeModel, universeView, side, this);
		universeSideViewController = new UniverseSideViewController(
				side, this, universeController);
		shipYardController = new ShipYardController(shipYardView, this);
		mktplcView = new MarketplaceView();
		mktplcController = new MarketplaceController(mktplcView, this);
		
		// Refactoring due here
		card = new MainPanel(main, config, dual, mktplcView, shipYardView);
		
		titleController = new TitleScreenViewController(main, card, this);
		configController = new ConfigViewController(config, card, this);
		
		super.getContentPane().add(card);
			
	}
	
	/**
	 * Starts a loop and plays music when the game is started
	 * @throws IOException 
	 * @throws InterruptedException 
	 */
	public final void music() throws IOException {
		
		audioPlayer = AudioPlayer.player;
		
		try {
			audioStream = new AudioStream(
					new FileInputStream("Sound/shape_shifters_939.wav"));
			data = audioStream.getData();
			loop = new ContinuousAudioDataStream(data);
			
		} catch (IOException ioe) {
			ioe.printStackTrace();
		} finally {
		
		audioStream.close();
		
		loop.close();
		
		}
		
		audioPlayer.start(loop);
		
		
	}
	
	// Fix need for this?
	/**
	 * Getter for the UniverseController
	 * 
	 * @return the controller for the UniverseModel
	 */
	public UniverseController getUniverseController() {
		return universeController;
	}
	
	/**
	 * Getter for the Marketplace
	 * 
	 * @return the controller for the Marketplace
	 */
	public MarketplaceController getMarketplaceController() {
		return mktplcController;
	}
	
	/**
	 * Gets the instance variable shipYardController
	 * @return the ShipYardController object from this class
	 */
	public ShipYardController getShipYardController() {
		return shipYardController;
	}
	
	/**
	 * shows the specified view on the card layout and displays it to the user
	 * 
	 * @param name the String value given to the View 
	 * so that it can be identified and shown
	 */
	public void show(String name) {
		card.getLayout().show(card, name);
	}
	
	/**
	 * Getter for the Player
	 * 
	 * @return the Player of the game
	 */
	public Player getPlayer() {
		return player;
	}
	
	/**
	 * Sets the player
	 * 
	 * @param player the player to be set
	 */
	public void setPlayer(Player player) {
		this.player = player;
	}
	
	/**
	 * Returns instance variable of AudioStream
	 * @return an AudioStream object
	 */
	public AudioStream getAudioStream() {
		return audioStream;
	}
	
	/**
	 * Returns instance variable of AudioPlayer
	 * @return an AudioPlayer object
	 */
	public AudioPlayer getAudioPlayer() {
		return audioPlayer;
	}
	
	/**
	 * Returns instance variable of AudioData
	 * @return an AudioData object
	 */
	public AudioData getAudioData() {
		return data;
	}
	
	/**
	 * Returns an instance variable of ContinuousAudioDataStream
	 * @return a ContinuousAudioDataStream object
	 */
	public ContinuousAudioDataStream getLoop() {
		return loop;
	}
	
	/**
	 * Sets the AudioStream instance variable
	 * @param audioStream what the instance variable should be set to
	 */
	public void setAudioStream(AudioStream audioStream) {
		this.audioStream = audioStream;
	}
	
	/**
	 * Sets the AudioPlayer instance variable
	 * @param audioPlayer what the instance variable should be set to
	 */
	public void setAudioPlayer(AudioPlayer audioPlayer) {
		this.audioPlayer = audioPlayer;
	}
	
	/**
	 * Sets the AudioData instance variable
	 * @param data what the instance variable should be set to
	 */
	public void setAudioData(AudioData data) {
		this.data = data;
	}
	
	/**
	 * Sets the ContinuousAudioDataStream instance variable
	 * @param loop what the instance variable should be set to
	 */
	public void setLoop(ContinuousAudioDataStream loop) {
		this.loop = loop;
	}
	
	/**
	 * saves the game
	 * 
	 * @throws IOException
	 */
	public void saveGame() {
		player.writeObject("player");
		((javamonsters.universe.model.DefaultUniverseModel) universeController
				.getUniverseModel()).writeObject("universe");
		//ObjectInputStream  
		System.out.println("Game saved");
	}
	
	/**
	 * tries to load the game
	 * 
	 * @return whether or not the load was successful
	 * @throws IOException 
	 */
	// ignore codepro; this is a fine name
	public boolean canLoadGame() throws IOException {
		try {
			playerIn = new ObjectInputStream(new FileInputStream("player.dat"));
			player = (Player) playerIn.readObject();
		
			universeIn = new ObjectInputStream(new FileInputStream("universe.dat"));
			universeController.setUniverseModel((UniverseModel) universeIn.readObject());
			
			//universeSideViewIn = new ObjectInputStream(new FileInputStream("sideview.dat"));
			//side.populateCargoList();
			System.out.println("Game loaded");
			
			return true;
		} catch (FileNotFoundException e) {
			JOptionPane.showMessageDialog(null, "There is no save file yet!");
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} finally {
			if (playerIn != null)
				playerIn.close();
			if (universeIn != null) 
				universeIn.close();
		}
		System.out.println("Game not loaded");
		return false;
	}
	
	/**
	 * @return the current system the player is in
	 */
	public SolarSystem getCurrSystem() {
		return player.getCurrSystem();
	}
	
	/**
	 * @return marketplace controller's marketplace reference
	 */
	public Marketplace getMarketplace() {
		return mktplcController.getMarketplace();
	}
	
	/**
	 * sets the current system the player is in
	 * 
	 * @param ss the current system the player is in
	 */
	public void setCurrSystem(SolarSystem ss) {
		player.setCurrSystem(ss);
	}
}
